package operate.rw;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.io.FileUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author zxc
 */
public class Main {

    /**
     * 程序主入口，读者优先的读写操作
     *
     * @param args
     */
    public static void main(String[] args) {
        List<List<Object>> lists = readThread("thread.txt");
//        List<List<Object>> lists = readThreadByJson("data.json");
        start(lists);
    }

    /**
     * 依此循环扫描readThread所给的lists集合的对象。
     * 并且根据第二个字段是'R'还是'W'来判断是读还是写进程
     *
     * @param lists
     */
    private static void start(List<List<Object>> lists) {
        // 实现写者与写者间、读者与写者间互斥
        Semaphore rwMutex = new Semaphore(1);
        // 用于改变 readCount 变量时实现互斥
        Semaphore rMutex = new Semaphore(1);
        // 用于实现读写公平
        Semaphore wMutex = new Semaphore(1);

        for (List<Object> object : lists) {
            double delay = (double) object.get(2);
            double persist = (double) object.get(3);
            String name = (String) object.get(0);

            if (object.get(1).equals("R")) {
                //创建读者进程
                new Thread(new Reader(rMutex, wMutex, rwMutex, delay, persist), name).start();
            } else if (object.get(1).equals("W")) {
                //创建写线程
                new Thread(new Writer(rwMutex, wMutex, delay, persist), name).start();
            }
        }
    }


    /**
     * 读取文件内容。将文件里的数据组装成list数组返回。
     * <ol>
     *     <li>第一个字段为id号，String类型</li>
     *     <li>第二个字段为线程类别，值'R','W'</li>
     *     <li>第三个字段为线程延迟时间，double类型</li>
     *     <li>第四个字段为线程读写操作时间，double类型<</li>
     * </ol>
     * <p>
     * 文件内容格式为:<br>
     * 1 R 3 5 <br>
     * 2 W 4 5 <br>
     * 3 R 5 2 <br>
     * 4 R 6 5 <br>
     * 5 W 5.1 3 <br>
     *
     * @param pathName 文件的相对路径或者绝对路径
     * @return lists 一个list数组，其中的元素为list
     */
    private static List<List<Object>> readThread(String pathName) {
        List<List<Object>> lists = new ArrayList<>();

        // 文件io操作
        try (FileReader reader = new FileReader(pathName);
             BufferedReader br = new BufferedReader(reader) // 建立一个对象，它把文件内容转成计算机能读懂的语言
        ) {
            String line;
            while ((line = br.readLine()) != null) {
                // 一次读入一行数据
                // 将文件里的数据Thread数据读取出来，这里使用的是用
                String[] split = line.split("\\s");
                List<Object> list = new ArrayList<>();
                list.add(split[0]);
                list.add(split[1]);
                list.add(Double.parseDouble(split[2]));
                list.add(Double.parseDouble(split[3]));
                lists.add(list);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return lists;
    }

    /**
     * 通过读取json内容来导入线程信息
     * 实际上并用不上...
     *
     * @param pathName
     * @return
     */
    private static List<List<Object>> readThreadByJson(String pathName) {
        File file = new File(pathName);
        List<List<Object>> lists = new ArrayList<>();
        String s = null;
        try {
            s = FileUtils.readFileToString(file, "utf-8");
            JSONObject jsonobject = JSON.parseObject(s);
            JSONArray data = jsonobject.getJSONArray("data");

            for (int i = 0; i < data.size(); i++) {
                String id = data.getJSONObject(i).getString("id");
                String entity = data.getJSONObject(i).getString("entity");
                Double delay = data.getJSONObject(i).getDouble("delay");
                Double persist = data.getJSONObject(i).getDouble("persist");
                List<Object> list = new ArrayList<>();
                list.add(id);
                list.add(entity);
                list.add(delay);
                list.add(persist);
                lists.add(list);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return lists;
    }

}